﻿using System.Linq.Expressions;

namespace Homework4_2
{
    /// <summary>这个程序借助了大语言模型，大概64句到96句没有看懂，如果可以的话，袁老师上课可以讲一下
    /// 用户输入一个四则运算表达式，比如 3.2 + 2 * 6，给出计算结果
    /// 这里要使用栈这个结构，要有一个操作数栈，一个操作符栈。
    /// </summary>
    internal class Program
    {
        static void Main(string[] args)
        {
            // 用户输入一个四则运算，将四则运算导入电脑中，调用Calculator函数计算四则运算结果，最后输出
            Console.WriteLine("输入一个四则运算表达式");
            string input = Console.ReadLine();
            double result = Calculator(input);
            Console.WriteLine($"计算结果是 {result}");
        }

        // 构造Calculator函数
        static double Calculator(string input)
        {
            // 创建两个栈，一个用于储存运算符号，一个用于储存数字
            Stack<double> values = new Stack<double>(); // 用于存放数字
            Stack<char> operators = new Stack<char>(); // 用于存放符号

            // 遍历输入的所有内容
            for (int i = 0; i < input.Length; i++)
            {
                // 判断是否是空格，如果是空格，则忽略
                if (char.IsWhiteSpace(input[i]))
                    continue;

                // 判断当前是数字或是小数点
                if (char.IsDigit(input[i]) || input[i] == '.')
                {
                    // 用num存储完成解析的数字
                    double num = 0;
                    bool isDecimal = false;
                    int decimalPlaces = 0;

                    // 遍历所有的数字，满足条件，长度小于总长度，是数字，遇到非数字或者小数点后停止
                    while (i < input.Length && (char.IsDigit(input[i]) || input[i] == '.'))
                    {
                        if (input[i] == '.')
                        {
                            isDecimal = true;
                            i++;
                            continue;
                        }

                        if (isDecimal)
                        {
                            num = num * 10 + (input[i] - '0');
                            decimalPlaces++;
                        }
                        else
                        {
                            num = num * 10 + (input[i] - '0');
                        }
                        i++;
                    }
                    i--;

                    // 如果是小数，调整小数点位置
                    if (isDecimal)
                    {
                        num /= Math.Pow(10, decimalPlaces);
                    }

                    // 将解析出的数字压入操作数栈
                    values.Push(num);
                }
                // 检查当前字符是否是运算符
                else if (IsOperator(input[i]))
                {
                    // 处理运算符栈，根据运算符的优先级决定是否先应用栈顶的运算符
                    while (operators.Count > 0 && Precedence(operators.Peek()) >= Precedence(input[i]))
                    {
                        ApplyOperator(operators, values);
                    }
                    // 将当前运算符压入运算符栈
                    operators.Push(input[i]);
                }
            }

            // 处理剩余的运算符
            while (operators.Count > 0)
            {
                ApplyOperator(operators, values);
            }

            // 返回最终结果
            return values.Pop();
        }

        static bool IsOperator(char c)
        {
            // 检查字符是否是运算符
            return c == '+' || c == '-' || c == '*' || c == '/';
        }

        static int Precedence(char op)
        {
            // 返回运算符的优先级
            if (op == '+' || op == '-') return 1;
            if (op == '*' || op == '/') return 2;
            return 0;
        }

        static void ApplyOperator(Stack<char> operators, Stack<double> values)
        {
            // 弹出运算符
            char op = operators.Pop();
            // 弹出两个操作数
            double b = values.Pop();
            double a = values.Pop();

            // 根据运算符执行相应的计算
            switch (op)
            {
                case '+':
                    values.Push(a + b);
                    break;
                case '-':
                    values.Push(a - b);
                    break;
                case '*':
                    values.Push(a * b);
                    break;
                case '/':
                    values.Push(a / b);
                    break;
            }
        }
    }
}